<?php
/**
 * s3CinchBaseBackup
 *
 * base backup class
 *
 * @category   Backup Types
 * @package    s3Cinch v1.0
 * @author     Stephen Gray <stephen@zgsolutions.co.uk>
 * @copyright  2010 Stephen Gray
 * @since      Sun 10 Jan 10 09:43
 */
abstract class s3CinchBaseBackup
{
    /**
     * string $_mainData
     *
     * local property for main data
     *
     * @var    string
     * @access protected
     */
    protected $_mainData;

    /**
     * string $_archiveFilePath
     *
     * location of file to be sent to s3
     *
     * @var    string
     * @access protected
     */
    protected $_archiveFilePath;

    /**
     * string $_bucketFileFolder
     *
     * folder to store the file in on the s3 
     * bucket
     *
     * @var    string
     * @access protected
     */
    protected $_bucketFileFolder;

    /**
     * void __construct ( string $data )
     *
     * set $data to local property
     *
     * @return void
     *
     * @access public
     */
    public function __construct($data)
    {
        $this->_mainData = $data;
    }

    /**
     * void createArchive ( )
     *
     * create the archive file to be sent
     * this is different per type of backup
     *
     * @return void
     *
     * @throws s3ArchiveException
     * @access abstract public
     */
    abstract public function createArchive();

    /**
     * void sendFile ( bool $keepLocals = true )
     *
     * split file if too big and upload files
     * to s3
     *
     * @param  bool $keepLocals
     * @return void
     *
     * @throws s3TransferException/s3ArchiveException
     * @access public
     */
    public function sendFile($keepLocals = true)
    {
        global $config;

        $keepLocals = ($keepLocals == '1' || $keepLocals) ? true : false;

        $fileSize = filesize($this->_archiveFilePath);
        $files = array();
        if (($fileSize/1000000) >= $config['general']['max_file_size'])
        {
            $this->log('Archive file is bigger than max_file_size ('.$config['general']['max_file_size'].'MB) at '.$fileSize.' bytes, splitting required.');

            /**
             * split the file up
             */
            $command = $config['general']['split_bin'].' --bytes='.$config['general']['max_file_size'].'m -d '.$this->_archiveFilePath.' '.$this->_archiveFilePath.'.p'; 
            $this->log('Command: '.$command);

            $output = shell_exec('split --bytes='.$config['general']['max_file_size'].'m -d '.$this->_archiveFilePath.' '.$this->_archiveFilePath.'.p'); 
            if (!empty($output))
            {
                throw new s3ArchiveException('Problem splittings archive, skipping this file.');
            }

            /**
             * split worked, remove original archive file and
             * add new split files to file array to be sent
             */

            unlink($this->_archiveFilePath);
            $files = glob($this->_archiveFilePath.'*');
            $this->log('Successfully split file into '.count($files).' files of '.$config['general']['max_file_size'].'MB or less and removed original archive file.');
        }
        else
        {
            $this->log('Archive file is '.$fileSize.' bytes, no splitting needed.');
            $files[] = $this->_archiveFilePath;
        }

        $s3Obj = new S3($config['amazon_s3_account']['access_key_id'], $config['amazon_s3_account']['secret_access_key']);
        $s3Obj->useSSL = false;

        /**
         * make sure the bucket exists
         */
        $this->_checkBucket($s3Obj, $config['amazon_s3_account']['bucket_name']);

        /**
         * upload to s3
         */
        foreach ($files as $filePath)
        {
            $bucketPath = $this->_bucketFileFolder.'/'.end(explode('/', $filePath));
            $s3Obj->putObjectFile($filePath, $config['amazon_s3_account']['bucket_name'], $bucketPath, S3::ACL_PRIVATE);
            if (!$keepLocals)
            {
                unlink($filePath);
                $this->log('Successfully uploaded file to '.$bucketPath.' and removed local copy.');
            }
            else
            {
                $this->log('Successfully uploaded file to '.$bucketPath.'.');
            }
        }

        $this->log('');
    }

    /**
     * void _checkBucket ( S3 &$s3Obj , string $bucketName )
     *
     * if given bucket does not exist, create
     * it
     *
     * @param  S3 &$s3Obj
     * @param  string $bucketName
     * @return void
     *
     * @access protected
     */
    protected function _checkBucket(&$s3Obj, $bucketName)
    {
        global $config;
        if (!in_array($bucketName, $s3Obj->listBuckets()))
        {
            if ($config['amazon_s3_account']['bucket_location'] == 'EU')
            {
                $s3Obj->putBucket($bucketName, S3::ACL_PRIVATE, 'EU');
            }
            else
            {
                $s3Obj->putBucket($bucketName, S3::ACL_PRIVATE);
            }
        }
    }

    /**
     * void _checkForFolder ( string $folderName )
     *
     * if a given folder does not exist in the 
     * archives folder, create it
     *
     * @param  string $folderName
     * @return void
     *
     * @access protected
     */
    protected function _checkForFolder($folderName)
    {
        global $config;
        if (!is_dir($config['dirs']['archives'].'/'.$folderName))
        {
            mkdir($config['dirs']['archives'].'/'.$folderName);
        }
    }

    /**
     * void log ( string $message )
     *
     * log a message to the main log file
     *
     * @return void
     *
     * @access protected
     */
    protected function log($message)
    {
        global $config;
        s3CinchUtils::log($config['dirs']['log'].'/'.$config['logs']['main_file'], $message);
    }
}
